#include "FrostedRefractionMaterial.h"
#include "Integrator.h"

FrostedRefractionMaterial::FrostedRefractionMaterial(Double ior, Double fuzziness, Float refractionIntensity, int sampleCount) : RefractionMaterial(ior, refractionIntensity) {
	this->fuzziness = fuzziness;
	this->sampleCount = sampleCount;
}

FrostedRefractionMaterial::FrostedRefractionMaterial(shared_ptr<Material> material, Double ior, Double fuzziness, Float refractionIntensity, int sampleCount) : RefractionMaterial(material, ior, refractionIntensity) {
	this->fuzziness = fuzziness;
	this->sampleCount = sampleCount;
}


void FrostedRefractionMaterial::setSampleCount(int sampleCount) {
	this->sampleCount = sampleCount;
}

Color FrostedRefractionMaterial::shade(const Scene * scene, const Ray & ray, const IntersectResult &intersect, const TraceState & traceState) const {
	Color refraction;
	Double kr = fresnel(ray.dir, intersect.normal, ior);
	if (kr < 1) {
		Vector3 refractDir = refract(ray.dir, intersect.normal, ior);
		if (!refractDir.isZero()) {
			Ray refractionRay(intersect.position);
			Vector3 random;
			for (int i = 0; i < sampleCount; i++) {
				random = randomPointInUnitSphere();
				random *= fuzziness;
				refractionRay.dir = (refractDir + random);
				refractionRay.dir.normalize();
				refraction += (scene->getIntegrator()->Li(scene, refractionRay, traceState) *= Float(1 - kr));
			}
			refraction /= sampleCount;
		}
	}

	Vector3 reflectDir = reflect(ray.dir, intersect.normal);
	Color reflection = scene->getIntegrator()->Li(scene, Ray(intersect.position, reflectDir), traceState);
	reflection *= Float(kr);

	refraction += reflection;
	refraction *= strength;

	return material ? refraction * material->shade(scene, ray, intersect, traceState) : refraction;
}

Color FrostedRefractionMaterial::getTransparentColor(const Scene * scene, const Ray & ray, const IntersectResult & intersect) const {
	return material ? strength *= material->getTransparentColor(scene, ray, intersect) : strength * Colors::White;
}
